/* -*- C++ -*- */
/*
 
 .---=||||[ B L O O D Y ]|||||\*\*----------....
 |                                                              |
 |    THE  M O S T   B L O O D Y  GAME EVER!                    |
 |                                                              |
 |    bloody harvest is coming... soon,                         |
 |                                              heil Satan!     |
 !                                                              !
 .                                                              ,
  ~~~~-------------\*\*-~




 Name-Space: {core, logic, editor}
 Module: {draw, coll, scgr, ...}
 Class: <name of class>
 Last modification:  <author>, <time>

 TODO:
 <-------- todo #1 ---------->
 <-------- todo #2 ---------->
 <-------- todo #3 ---------->
        ............
 <-------- todo #n ---------->

 FIX:
 <-------- fix #1 ----------->
 <-------- fix #1 ----------->
         ..........
 <-------- fix #n ----------->




 
 
 */
#ifndef __anonymous_Config_Header_File__
#define __anonymous_Config_Header_File__

#include "common.h"
#include <string>
#include <fstream>
#include <sstream>
#include <iostream>
#include <map>
#include "core/vmath.h"
#include "core/exceptions.h"

namespace core
{
	/**
	 * Class providing read access to config file.
	 */
	class Config
	{
		public:
		
			/**
			 * An item in config file
			 */
			struct Item
			{
					/**
					 * Name of an item
					 */
					std::string name;
			
					/**
					 * Value of an item
					 */
					std::string value;
		
					/**
					 * Constructor of item
					 */
					Item(std::string aName, std::string aValue):
						name(aName),value(aValue){}
			
					/**
					 * Converts item into antoher type
					 * @note To get string interpretation of value, use value 
					 * attribute directly instead of calling this function.
					 */
					template <class T>
					void to(T& ret) const  {
						std::istringstream iss(value);
						iss >> ret;
					}

					//template <>
					void to(String& ret) const { ret = value; }

					//template <>
					void to(Vector3f& ret) const
					{
						std::istringstream iss(value);
						iss >> ret.x >> ret.y >> ret.z;
					}

					//template <>
					void to(Vector2f& ret) const
					{
						std::istringstream iss(value);
						iss >> ret.x >> ret.y;
					}
					
					//template <>
					void to(Vector4f& ret) const
					{
						std::istringstream iss(value);
						iss >> ret.x >> ret.y >> ret.z >> ret.w;
					}

					void toBlendEnum(GLenum& glen) const
					{
						if (value == "zero")
						{
							glen = GL_ZERO;
							std::cout <<  "zero" << std::endl;
						}
						else if (value == "one")
						{
							glen = GL_ONE;
						}
						else if (value == "dcol")
						{
							glen = GL_DST_COLOR;
						}
						else if (value == "1-dcol")
						{
							glen = GL_ONE_MINUS_DST_COLOR;
						}
						else if (value == "salpha")
						{
							glen = GL_SRC_ALPHA;
						}
						else if (value == "1-salpha")
						{
							glen = GL_ONE_MINUS_SRC_ALPHA;
						}
						else if (value == "scol")
						{
							glen = GL_SRC_COLOR;
						}
						else if (value == "1-scol")
						{
							glen = GL_ONE_MINUS_SRC_COLOR;
						}
						else if (value == "dalpha")
						{
							glen = GL_DST_ALPHA;
						}
						else if (value == "1-dalpha")
						{
							glen = GL_ONE_MINUS_DST_ALPHA;
						}
						else
						{
							throw BaseException("No such blending value %s", value.c_str());
						}
					}

					bool toBool() const
					{
						bool ret = false;
						if (value == "true")
						{
							ret = true;
						}
						else if (value == "false")
						{
							ret = false;
						}
						else
						{
							std::cerr << "No such bool value" << value  << std::endl;
						}
						return ret;
					}



			
		
			};
		
			/**
			 * Config constructor. Reads configuration file.
			 * @param fileName Path to configuration file
			 */
			Config(const String& fileName);
		
			/**
			 * Access operator to items
			 */
			const Item& operator[](std::string name) const;

			/**
			 * Test if named item is in config file
			 */
			bool hasKey(std::string name) const;
		
		private:
			/**
			 * Filename of config file
			 */
			String fileName;
			/**
			 * Storage of items
			 */
			std::map<std::string, Item> data;
	
			/**
			 * Removes beginning and ending spaces of string.
			 */
			static std::string trim(std::string str);
	};
}



#endif //__anonymous_Config_Header_File__
